#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>

using namespace std;

//多态的两个条件：1.必须是重写的虚函数 2.必须由基类的指针或者引用调用
//虚函数重写的两个条件：函数名、参数、返回值相同，虚函数
//虚函数重写的两个例外：1.协变：返回值可以不同，但必须是父子关系的指针或者引用  2.派生类可以不加virtual
class Person
{
public:
	Person(const char* name = "Peter")
		:_name(name)
	{

	}
	//virtual void print () final
	//final可以防止虚函数的重写 也可以防止类被继承
	virtual void print()
	{
		cout << "买票--全价" << endl;
	}

	virtual void print2()
	{
		cout << "print2()" << endl;
	}

	virtual void print3()
	{
		cout << "print3()" << endl;
	}
protected:
	string _name;
};

//override : 检查派生类虚函数是否重写了基类某个虚函数，如果没有重写编译报错
class Student :public Person
{
public:
	Student(const char* name = "Lilei", int id = 1000)
		:Person(name)
		, _id(id)
	{

	}
	virtual void print() override
	{
		cout << "买票--半价 "<< endl;
	}

	virtual void print4()
	{
		cout << "print4()" << endl;
	}

protected:
	int _id;
};

void test1(Person& p)
{
	p.print();
}

//析构函数是重写的虚函数
//编译器会对类对象的析构函数进行处理，函数名都为destroy
//如果析构函数不是重写的虚函数 可能会导致内存泄漏
class AA
{
public:
	AA(int a = 1)
		:_a(a)
	{}
	 ~AA()
	{
		_a = 0;
		cout << "~AA()" << endl;

	}
protected:
	int _a;
};

class BB: public AA
{
public:
	BB(int b = 0)
		:_b(b)
	{}
	 ~BB()
	{
		_b = 0;
		cout << "~BB()" << endl;
	}
protected:
	int _b;
	int* ptr = new int(0);
};

void test2()
{
	//不使用虚函数的重写 会调两次基类的析构函数 不会调用派生类的析构函数-->可能会导致派生类的内存泄漏
	AA* a = new AA;
	delete a;
	
	a = new BB;
	delete a;  //a->destroy()调用析构函数看的是当前者的类型(基类)   --->    operator delete()

}

//打印虚函数表--函数指针数组
typedef void(*FUN_PTR)();
void display(FUN_PTR* table)
{
	for (int i = 0; table[i] != nullptr; i++)
	{
		printf("[%d]:%p->", i, table[i]);
		FUN_PTR f = table[i];
		f();
	}

	printf("\n");
}

//多继承中的多态
class Base1
{
public: 
	virtual void func1()
	{
		cout << "Base1::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base1::func2()" << endl;
	}

protected:
	int _b1;
};

class Base2
{
public:
	virtual void func1()
	{
		cout << "Base2::func1()" << endl;
	}
	virtual void func2()
	{
		cout << "Base2::func2()" << endl;
	}

protected:
	int _b2;
};

class Derive:public Base1,public Base2
{
public:
	virtual void func1()
	{
		cout << "Derive::func1()" << endl;
	}
	virtual void func3()
	{
		cout << "Derive::func3()" << endl;
	}

protected:
	int _d1;
};

//笔试题
class a
{
public:
    virtual void func(int val = 1) { std::cout << "a->" << val << std::endl; }
	virtual void test()
	{
		func();
	}
};

class b : public a
{
public:
    void func(int val = 0) { std::cout << "b->" << val << std::endl; }

};

void test3()
{
    b* p = new b;
    p->test();
}

//抽象类--包含纯虚函数 --> 间接强制派生类对纯虚函数进行重写
class Car
{
public:
	virtual void Drive() = 0;
};
class Benz :public Car
{
public:
	virtual void Drive()
	{
		cout << "Benz-舒适" << endl;
	}
};
class BMW :public Car
{
public:
	virtual void Drive()
	{
		cout << "BMW-操控" << endl;
	}
};

void cardisplay(Car* p)
{
	p->Drive();
}

void test4()
{
	cardisplay(new Benz);
	cardisplay(new BMW);
}

//多态中的菱形继承和菱形虚拟继承
class A
{
public:
	virtual void func1()
	{
		cout << "A::func1" << endl;
	}
public:
	int _a;
};

//class B : public A
class B : virtual public A
{
public:
	virtual void func1()
	{
		cout << "B::func1" << endl;
	}

	virtual void func2()
	{
		cout << "B::func2" << endl;
	}
public:
	int _b;
};

//class C : public A
class C : virtual public A
{
public:
	virtual void func1()
	{
		cout << "C::func1" << endl;
	}

	virtual void func2()
	{
		cout << "C::func2" << endl;
	}
public:
	int _c;
};

class D : public B, public C
{
public:
	virtual void func1()
	{
		cout << "D::func1" << endl;
	}

	virtual void func3()
	{
		cout << "D::func3" << endl;
	}
public:
	int _d;
};

void test5()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
}

//验证虚表存在哪里
void test6()
{
	int a = 0;
	printf("栈区：%p\n", &a);

	int* b = new int(1);
	printf("堆区：%p\n", b);

	static int c = 10;
	printf("静态区（数据段）：%p\n", &c);

	const char* d = "hello world";
	printf("常量区（代码段）：%p\n", d);

	A aa;
	printf("虚函数表：%p\n", *(int*)&aa);
}


//多态调用与指向的对象有关
//普通函数的调用 与当前者的类型有关
int main()
{
	Student s;
	Person& p = s;
	test1(p);

	Person pp;
	test1(pp);
	cout << "-----------------------------" << endl;

	int vpt1 = *((int*)&pp);
	display((FUN_PTR*)vpt1);

	int vpt2 = *((int*)&s);
	display((FUN_PTR*)vpt2);
	cout << "-----------------------------" << endl;

	Derive d;
	int vpt3 = *((int*)&d);
	display((FUN_PTR*)vpt3);

	Base2* ptr = &d;
	int vpt4 = *((int*)ptr);
	//int vpt4 = *((int*)((char*)&d + sizeof(Base2)));
	display((FUN_PTR*)vpt4);
	cout << "-----------------------------" << endl;

	Derive dd;
	Base1* ptr1 = &dd;
	ptr1->func1();

	Base2* ptr2 = &dd;
	ptr2->func1();

	Derive* ptr3 = &dd;
	ptr3->func1();
	cout << "-----------------------------" << endl;

	test2();
	cout << "-----------------------------" << endl;

	test3();
	cout << "-----------------------------" << endl;

	test4();
	cout << "-----------------------------" << endl;

	test5();

	test6();



	return 0;
}